//
//  SRAudioPlayerManager
//  EnglishTalk
//
//  Created by huyanming on 15/8/1.
//  Copyright (c) 2015年 Feizhu Tech. All rights reserved.
//

#import "SRAudioPlayerManager.h"
//#import "FZMessageConstants.h"
#import "FZMCCacheManager.h"

#import <AFURLSessionManager.h>
#import "SRCommonConstants.h"

static void *FZRecordAVPlayerStatusObservationContext = &FZRecordAVPlayerStatusObservationContext;

@interface SRAudioPlayerManager ()<AVAudioPlayerDelegate, AVAudioRecorderDelegate>

@property (strong, nonatomic) AVAudioPlayer *soundPlayer;
@property (strong, nonatomic) NSTimer *timer;

@property (strong, nonatomic) FZMCCacheManager *diskCacheManager;
//@property (strong, nonatomic) AVPlayer *recordPlayer;//播放用户录音，支持在线播放
//@property (strong, nonatomic) AVPlayerItem *playerItem;


@property (assign, nonatomic) NSTimeInterval startTime;//播放mp3开始时间
@property (assign, nonatomic) NSTimeInterval endTime;//结束时间

    //录音器
@property (strong, nonatomic) AVAudioRecorder *recorder;
@property (strong, nonatomic) NSString *recordFilePath;//当前录音的文件路径
@property (strong, nonatomic) CADisplayLink *displayLink;//定时器刷新
@property (assign, nonatomic) CGFloat displayLinkTime;//定时器时间


@end

@implementation SRAudioPlayerManager

+ (SRAudioPlayerManager*)sharedInstance {
    static SRAudioPlayerManager* sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(& onceToken,^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}


- (instancetype)init {
    self = [super init];
    if (self) {
        self.diskCacheManager = [FZMCCacheManager defaultManager];
        //开启红外感应
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(sensorStateChange:)
                                                     name:@"UIDeviceProximityStateDidChangeNotification"
                                                   object:nil];
        self.audioRate = 1.0;
    }
    
    return self;
}

- (void)setAudioRate:(CGFloat)audioRate {
    if (_audioRate != audioRate) {
        _audioRate = audioRate;
        if (self.soundPlayer) {
                //        self.soundPlayer.rate = audioRate;
//            NSLog(@"************setAudioRate: %f", self.soundPlayer.rate);
            if (self.soundPlayer.isPlaying) {
                [self.soundPlayer stop];
            }
                //重设播放器,否则调速无效
            NSString *filePath = [NSString stringWithFormat:@"%@", self.audioFilePath];
            self.audioFilePath = nil;
            [self setRecordAudioWithFilePath:filePath];
        }
    }
 
}

- (BOOL)isPlaying {
    return self.soundPlayer.isPlaying;
}


- (void)setRecordAudioWithFilePath:(NSString*)filePath
{
    [self setRecordAudioWithFilePath:filePath startTime:0. endTime:0.];
}

- (void)setRecordAudioWithFilePath:(NSString*)filePath startTime:(NSTimeInterval)startTime endTime:(NSTimeInterval)endTime
{
    self.startTime = startTime;
    self.endTime = endTime;
    
    NSURL *soundUrl = [[NSURL alloc] initFileURLWithPath:filePath];
    [self resetSoundPlayerWithURL:soundUrl startTime:startTime];
}

- (void)resetLastAudioCellStopPlaying {
    [self stopPlayRecordAudio];
}

- (void)resetSoundPlayerWithURL:(NSURL *)url {
    [self resetSoundPlayerWithURL:url startTime:0.f];
}

- (void)resetSoundPlayerWithURL:(NSURL *)url startTime:(NSTimeInterval)startTime{
    
    if (!url) {
        return;
    }
    
    NSString *path = url.path;
    if (!self.audioFilePath || ![self.audioFilePath isEqualToString:path]) {
            //不同的mp3，则重新加载
        
        self.audioFilePath = url.path;
        self.audioFileName = [self.audioFilePath lastPathComponent];
        NSError *error = nil;
        self.soundPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url  error:&error];
        if (error) {
            NSData *audioData = [NSData dataWithContentsOfURL:url];
            self.soundPlayer = [[AVAudioPlayer alloc] initWithData:audioData error:&error];
        }
     
//        self.soundPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url  error:&error];
//        self.soundPlayer = [[AVAudioPlayer alloc] initWithData:audioData fileTypeHint:AVFileTypeWAVE error:&error];
        
        UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
        AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,
                                sizeof(sessionCategory),
                                &sessionCategory);
        
        UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
        AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,
                                 sizeof (audioRouteOverride),
                                 &audioRouteOverride);
        
        if (error) {
            NSLog(@"sound error:%@", error);
            
            if (self.audioRecorderFailureBlock) {
                self.audioRecorderFailureBlock(@"音频解析失败");
            }
            
            return;
        }
       
        self.soundPlayer.enableRate = YES;
        self.soundPlayer.rate = self.audioRate;
        
        [self.soundPlayer prepareToPlay];
    }
    
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
    [[AVAudioSession sharedInstance] setActive:YES error: nil];
    self.soundPlayer.currentTime = startTime;
    self.soundPlayer.delegate = self;
    self.soundPlayer.volume = 0.6;
}


- (void)resetSoundPlayerWithData:(NSData *)data {
    NSError *error = nil;
    self.soundPlayer = [[AVAudioPlayer alloc] initWithData:data error:&error];
    
    UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback;
    AudioSessionSetProperty(kAudioSessionProperty_AudioCategory,
                            sizeof(sessionCategory),
                            &sessionCategory);
    
    UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
    AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,
                             sizeof (audioRouteOverride),
                             &audioRouteOverride);
    
    if (error) {
        NSLog(@"sound error:%@", error);
    }
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
    [[AVAudioSession sharedInstance] setActive:YES error: nil];
    
    [self.soundPlayer prepareToPlay];
    self.soundPlayer.currentTime = 0.0f;
    self.soundPlayer.delegate = self;
}

- (NSString *)playingFileName {
    return self.audioFileName;
}

- (void)setRecordAudioWithFileURL:(NSString *)fileURL {
    
        //    NSURL *filePath = [NSURL fileURLWithPath:fileURL];
        //    [self playRecordAudioWithURLPath:filePath];
        //下载
    self.audioFileName = [fileURL lastPathComponent];
    
    NSString *fullPath = [FZMCCacheManager filePathAtCacheForFileName:self.audioFileName ];
    if (fullPath) {
            //存在缓存
        NSURL *filePath = [NSURL fileURLWithPath:fullPath];
        [self playRecordAudioWithURLPath:filePath];
    } else {
        
        [self downloadRecordFileURL:fileURL fileName:self.audioFileName];
    }
}
- (void)downloadRecordFileURL:(NSString *)fileURL fileName:(NSString *)fileName {
    NSString *urlString = fileURL;
    
    NSURL *URL = [NSURL URLWithString:urlString];
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
    
    WEAKSELF
    NSURLRequest *request = [NSURLRequest requestWithURL:URL];
    NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath,NSURLResponse *response) {
        
        NSString *cacheDir = [CacheDirectory stringByAppendingPathComponent:@"AudioCache"];
        NSString *urlPath = [cacheDir stringByAppendingPathComponent:fileName];
        NSURL *downloadURL = [NSURL fileURLWithPath:urlPath];
        return downloadURL;
            //        NSURL *downloadURL = [[NSFileManager defaultManager] URLForDirectory:self.diskCacheManager.cacheDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
            //        return [downloadURL URLByAppendingPathComponent:[response suggestedFilename]];
        
    } completionHandler:^(NSURLResponse *response,NSURL *filePath, NSError *error) {
            //此处已经在主线程了
        
        if (error) {
                //下载错误
//            [weakSelf resetLastAudioCellStopPlaying];
            if (weakSelf.audioPlayerCompletedBlock) {
                weakSelf.audioPlayerCompletedBlock(YES);
            }
        } else if ([weakSelf.audioFileName isEqualToString:[filePath lastPathComponent]]) {
            NSLog(@"donwload filePath:%@", filePath);
            [weakSelf playRecordAudioWithURLPath:filePath];
        }
    }];
    
    [downloadTask resume];
}

- (BOOL)startPlayRecordAudio {
    BOOL isSuccess = NO;
//    if (self.startTime > 0.1) {
//        isSuccess = [self.soundPlayer play];//self.startTime];
//    } else {
        isSuccess = [self.soundPlayer play];
//    }
    if (isSuccess) {
        [self.timer invalidate];
        self.timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(updateRecordProgress:) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
        [self.timer fire];
    }
    
    return isSuccess;
}

- (void)setRecordAudioProgress:(CGFloat)progress autoPlay:(BOOL)autoPlay {
    NSTimeInterval currentTime = progress * self.soundPlayer.duration;
    
    if (autoPlay) {
        self.soundPlayer.currentTime = currentTime;
        [self.soundPlayer play];
        
        [self.timer fire];
    } else {
        self.soundPlayer.currentTime = currentTime;
    }
}

- (void)pauseRecordAudio {
    [self.soundPlayer pause];
    [self setTimerFire:NO];

}

- (void)stopPlayRecordAudio {
    if (self.soundPlayer) {
        [self.soundPlayer stop];
    }
    [self setTimerFire:NO];
    
    if (self.audioPlayerCompletedBlock) {
        self.audioPlayerCompletedBlock(NO);
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:SRAudioMP3DidPauseFinishedNotification object:nil];
    });
}


- (void)setAutoScrollProgress:(BOOL)isAuto {
    [self setTimerFire:isAuto];
}

- (void)setTimerFire:(BOOL)isFire {
    if (isFire) {
        self.timer.fireDate = [NSDate distantPast];
        [self.soundPlayer play];
    } else {
//        self.timer.fireDate = [NSDate distantFuture];
        [self.timer invalidate];
    }
}

- (void)updateRecordProgress:(NSTimer *)timer {
    
//    NSLog(@"updateRecordProgress:currentTime:%f--Duration:%f--endTime:%f", self.soundPlayer.currentTime, self.soundPlayer.duration,  self.endTime);

    if (self.endTime > 0.1 && self.soundPlayer.currentTime >= self.endTime) {
            //达到结束时间，则暂停
//        NSLog(@"pauseRecordAudio:currentTime:%f----endTime:%f", self.soundPlayer.currentTime, self.endTime);

        [self stopPlayRecordAudio];
        
        if (self.audioPlayerTimeBlock) {
            self.audioPlayerTimeBlock(self.soundPlayer.currentTime);
        }
    }
    
    if (self.soundPlayer && self.audioPlayerProgressBlock) {
        CGFloat progress = self.soundPlayer.currentTime / self.soundPlayer.duration;
        if (progress >= 0 && progress <= 1.0) {
            self.audioPlayerProgressBlock(progress);
        }
        
        if (self.audioPlayerTimeBlock) {
            self.audioPlayerTimeBlock(self.soundPlayer.currentTime);
        }
    }
}

#pragma mark - AVAudioPlayerDelegate

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
    if (player == self.soundPlayer) {
        [self.timer invalidate];
        [self resetLastAudioCellStopPlaying];
        
        if (self.audioPlayerCompletedBlock) {
            self.audioPlayerCompletedBlock(YES);
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSNotificationCenter defaultCenter] postNotificationName:SRAudioMP3DidPlayFinishedNotification object:nil];
        });
    }
}

/* if an error occurs while decoding it will be reported to the delegate. */
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error {
    [self.timer invalidate];
    [self resetLastAudioCellStopPlaying];

    if (self.audioPlayerCompletedBlock) {
        self.audioPlayerCompletedBlock(NO);
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:SRAudioMP3DidPlayFinishedNotification object:nil];
    });
}

- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player {
    
}

- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withOptions:(NSUInteger)flags  {
    
}

- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withFlags:(NSUInteger)flags{
    
}

#pragma mark - Record Player 播放录音

- (void)setRecordAudioWithFileName:(NSString *)fileName {
    self.audioFileName = fileName;
 
    NSString *fullPath = [FZMCCacheManager mp3PathWithName:fileName bookID:nil];
    if (fullPath) {
        //存在缓存
        NSURL *filePath = [[NSURL alloc] initFileURLWithPath:fullPath];
        [self playRecordAudioWithURLPath:filePath];
    }
}

- (void)recordDidPlayToEnd:(NSNotification *)notification {
    
    [self resetLastAudioCellStopPlaying];
    if (self.audioPlayerCompletedBlock) {
        
        self.audioPlayerCompletedBlock(YES);
    }
}

/**
 *  播放失败
 *
 *  @param notification
 */
- (void)recordFailedPlayToEnd:(NSNotification *)notification {
    [self resetLastAudioCellStopPlaying];
    if (self.audioPlayerCompletedBlock) {
        self.audioPlayerCompletedBlock(YES);
    }
}

- (void)playRecordAudioWithURLPath:(NSURL *)filePath {
    [self resetSoundPlayerWithURL:filePath];
    BOOL success = [self startPlayRecordAudio];
    if (!success) {
        [self resetLastAudioCellStopPlaying];
    }
}

/**
 *  播放语音数据
 *
 *  @param data
 */
- (void)playRecordAudioWithData:(NSData*)data{
    if(!data){
        return;
    }
    [self resetSoundPlayerWithData:data];
    BOOL success = [self startPlayRecordAudio];
    if (!success) {
        [self resetLastAudioCellStopPlaying];
        if (self.audioPlayerCompletedBlock) {
            self.audioPlayerCompletedBlock(NO);
        }
        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSNotificationCenter defaultCenter] postNotificationName:SRAudioMP3DidPlayFinishedNotification object:nil];
        });
    }
}

- (void)observeValueForKeyPath:(NSString*) path
                      ofObject:(id)object
                        change:(NSDictionary*)change
                       context:(void*)context
{
    if (context == FZRecordAVPlayerStatusObservationContext) {
        AVPlayerItemStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
        switch (status)
        {
            case AVPlayerItemStatusUnknown:
            {
                [self resetLastAudioCellStopPlaying];
                if (self.audioPlayerCompletedBlock) {
                    self.audioPlayerCompletedBlock(YES);
                }
            }
                break;
            case AVPlayerItemStatusReadyToPlay:
            {
            } break;
            case AVPlayerItemStatusFailed:
            {
                [self resetLastAudioCellStopPlaying];
                if (self.audioPlayerCompletedBlock) {
                    self.audioPlayerCompletedBlock(YES);
                }
                dispatch_async(dispatch_get_main_queue(), ^{
                    [[NSNotificationCenter defaultCenter] postNotificationName:SRAudioMP3DidPlayFinishedNotification object:nil];
                });
            } break;
        }
    }
}

-(void)sensorStateChange:(NSNotificationCenter *)notification;
{
    if ([[UIDevice currentDevice] proximityState] == YES)
    {
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
        
    }
    else
    {
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
        if (!self.soundPlayer.isPlaying) {
            [[UIDevice currentDevice] setProximityMonitoringEnabled:NO];
        }
    }
}


#pragma mark - Audio Recorder 

-(void)prepareToRecorderOutputUrl:(NSString*)filePath{
        // Define the recorder setting
    if (!filePath) {
        return;
    }
    
    if (self.recorder) {
        self.recorder.delegate = nil;
        if (self.recorder.isRecording) {
            [self.recorder stop];
        }
        
        self.recorder = nil;
    }
    
    NSURL *outputFileURL = [NSURL fileURLWithPath:filePath];
    NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];
    [recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];

    [recordSetting setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
    [recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
    
    [recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];
    [recordSetting setValue:[NSNumber numberWithBool: NO] forKey:AVLinearPCMIsBigEndianKey];

//    NSDictionary *recordSetting = [[NSDictionary alloc] initWithObjectsAndKeys:
//                                   
//                                   [NSNumber numberWithFloat: 44100.0],AVSampleRateKey, //采样率
//                                   
//                                   [NSNumber numberWithInt: kAudioFormatLinearPCM],AVFormatIDKey,
//                                   
//                                   [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,//采样位数
//                                   默认 16
//                                   
//                                   [NSNumber numberWithInt: 2], AVNumberOfChannelsKey,//通道的数目
//                                   
//                                   [NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey,//大端还是小端
//                                   是内存的组织方式
//                                   
//                                   [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,nil];//采样信号是整数还是浮点数

        // Initiate and prepare the recorder
    self.recorder = [[AVAudioRecorder alloc] initWithURL:outputFileURL settings:recordSetting error:nil];
    self.recorder.delegate = self;
    self.recorder.meteringEnabled = YES;
//    [self.recorder prepareToRecord];
}

-(void)beginRecorder {
    if (!self.recorder.isRecording) {
        [self restartDisplayLink];
        
        AVAudioSession *session = [AVAudioSession sharedInstance];
        [session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
        [session setActive:YES error:nil];
        [self.recorder record];
    }
    
}

-(void)beginRecorderForDuration:(NSTimeInterval)duration {
    self.recorderDuration = duration;
    
    if (self.recorder.isRecording) {
        [self.recorder stop];
    }
    
    [self restartDisplayLink];
    
    AVAudioSession *session = [AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
    [session setActive:YES error:nil];
    [self.recorder recordForDuration:duration];
    
    if (self.audioRecorderBeginBlock) {
        self.audioRecorderBeginBlock(nil);
    }
}

-(void)stopRecorder {
    [self.recorder stop];
    [self stopDisplayLink];
    
//    if (self.audioRecorderCompletedBlock) {
//        self.audioRecorderCompletedBlock(YES);
//    }
}

-(void)updateMeters {
    [self.recorder updateMeters];
}
-(float)avaragePowerForChannelForIndex:(NSInteger)index {
    return [self.recorder averagePowerForChannel:index];
}

-(float)peakPowerForChannelForIndex:(NSInteger)index {
    return [self.recorder peakPowerForChannel:index];
}

- (BOOL)isRecording {
    if (self.recorder) {
        return self.recorder.isRecording;
    }
    return NO;
}

- (void)onDisplayLinkTimeRefresh:(CADisplayLink *)timer {
    self.displayLinkTime += 1/60.f;
    
    NSTimeInterval currentTime = self.recorder.currentTime;
    CGFloat progress = 0;
    if (currentTime >= self.recorderDuration){
        progress = 1.0;
    }
    else if (self.recorderDuration > 0) {
        progress = currentTime / self.recorderDuration;
    }
    
    if (self.audioRecorderProgressBlock) {
        self.audioRecorderProgressBlock(progress);
    }
    
    if (self.displayLinkTime >= self.recorderDuration) {
            //结束录音
        [self stopRecorder];
    }
}

- (void)stopDisplayLink {
    [self.displayLink invalidate];
    self.displayLink = nil;
}

- (void)restartDisplayLink {
    if (!self.displayLink) {
        self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onDisplayLinkTimeRefresh:)];
        [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
//        self.displayLink.preferredFramesPerSecond = 60;
    }
    
    self.displayLinkTime = 0;
}

#pragma mark -  AVAudioRecorderDelegate <NSObject>

/* audioRecorderDidFinishRecording:successfully: is called when a recording has been finished or stopped. This method is NOT called if the recorder is stopped due to an interruption. */
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag {
    if (flag) {
        NSLog(@"audioRecorderDidFinishRecording success:dTime:%f--duration:%f", self.displayLinkTime, self.recorderDuration);
        if (self.audioRecorderCompletedBlock) {
            self.audioRecorderCompletedBlock(YES);
        }
    }
}

/* if an error occurs while encoding it will be reported to the delegate. */
- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError * __nullable)error {
    NSLog(@"audioRecorderEncodeErrorDidOccur error:%@", error);
    if (self.audioRecorderFailureBlock) {
        self.audioRecorderFailureBlock(error.localizedDescription);
    }

}


@end
